#include "src/scene/light.h"

#include <iostream>
#include <stdlib.h>

#include "src/defines/rayState.h"
#include "src/scene/hbb/tree.h"


Light::Light(){
    color = Color(1.0, 1.0, 0.0);
    id = 0;
    selected = false;
//    projectionMap = NULL;
    energy = 1;

    srand ( time(NULL) );
}

Light::Light(unsigned int _id, const Color &_c, double _e) : id(_id), color(_c), energy(_e){
    selected = false;
//    projectionMap = NULL;

    srand ( time(NULL) );
}

Light::~Light(){
//    delete projectionMap;
}

double Light::attenuation(const unsigned int &_type, const double &_distance) const{
    switch(_type)
    {
        case CONSTANT_ATTENUATION:
            return 1;
        case LINEAR_ATTENUATION:
            return 1.0/_distance;
        case QUADRATIC_ATTENUATION:
            return pow(1.0/_distance, 2);
    }

    return 0;
}

bool Light::isOccluded(const NearestInfo &_nearest, const Vector3D &_toLight, HBBTree *_tree, const Vector3D &_position) const{

    Ray shadowRay(_nearest.point, _toLight);

    //!TODO: podeira tentar ver se o objeto é transparente, e se não tem outro objeto opaco na frente
    NearestInfo result;
    if(_tree->hit(shadowRay, &result, _nearest.object))
    {
        if(result.t > (_nearest.point-_position).length())
            return false;
        else
            return true;
    }

    return false;
}

Vector3D Light::objectMap(const Vector3D &_pos, Object *_object) const
{
    //tem que gerar fotons aleatórios na direção da bounding box
    //isso é feito pegnad um peso aleaorio para cada ponto da bounding box!
    const HBBBox &box = _object->getBoundingBox();
    Vector3D points[8];
    boxPoints(box.getMin(), box.getMax(), points);

    Vector3D result;
    for(unsigned int i = 0; i < 8; i++)
    {
        double xi = (rand()%101)/100.0;//vertical [0,1]
        result = result + (points[i] - _pos)* xi;
    }

    return result.normalize();
}
